package com.zjcloud.framework.aspectj;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 数据源监控切面，用于记录数据库连接的获取和释放
 *
 * @author zjcloud
 */
@Aspect
@Component
public class DataSourceMonitorAspect {

    private static final Logger log = LoggerFactory.getLogger(DataSourceMonitorAspect.class);

    /**
     * 定义切点 - 数据源获取连接方法
     */
    @Pointcut("execution(* javax.sql.DataSource.getConnection(..))") 
    public void dataSourceGetConnectionPointcut() {}

    /**
     * 定义切点 - 数据库连接关闭方法
     */
    @Pointcut("execution(* java.sql.Connection.close())") 
    public void connectionClosePointcut() {}

    /**
     * 环绕通知，记录数据源获取连接的日志
     *
     * @param joinPoint 连接点
     * @return 方法执行结果
     * @throws Throwable 执行异常
     */
    @Around("dataSourceGetConnectionPointcut()")
    public Object aroundGetConnection(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取数据源类名
        String dataSourceName = joinPoint.getTarget().getClass().getName();
        
        // 记录开始日志
        long startTime = System.currentTimeMillis();
        log.debug("开始获取数据库连接: {}", dataSourceName);
        
        // 执行原方法
        Object connection = null;
        try {
            connection = joinPoint.proceed();
            return connection;
        } catch (Throwable e) {
            log.error("获取数据库连接异常: {}, 异常信息: {}", dataSourceName, e.getMessage());
            throw e;
        } finally {
            // 记录结束日志
            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;
            log.debug("结束获取数据库连接: {}, 耗时: {}ms, 连接ID: {}", 
                    dataSourceName, costTime, connection != null ? connection.hashCode() : "null");
        }
    }

    /**
     * 环绕通知，记录数据库连接关闭的日志
     *
     * @param joinPoint 连接点
     * @return 方法执行结果
     * @throws Throwable 执行异常
     */
    @Around("connectionClosePointcut()")
    public Object aroundConnectionClose(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取连接对象
        Object connection = joinPoint.getTarget();
        int connectionId = connection.hashCode();
        
        // 记录开始日志
        log.debug("开始关闭数据库连接: {}", connectionId);
        
        // 执行原方法
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            log.error("关闭数据库连接异常: {}, 异常信息: {}", connectionId, e.getMessage());
            throw e;
        } finally {
            // 记录结束日志
            log.debug("结束关闭数据库连接: {}", connectionId);
        }
    }
}